建立好與資料庫的連線之後,接著就是實際的存取資料庫了
我們來看看 Laravel 是怎麼存取資料庫的。
Laravel 提供存取資料庫的兩種方式,分別是 Query Builder 以及 ORM。
今天我們先來看 Query Builder 的方式是怎麼實作的。
如果用 Query Builder 的方式存取,範例程式碼大約如下
use Illuminate\Support\Facades\DB;
$users = DB::table('users')->get();
這邊的 DB 一樣是一個 Facades,實作的地方不在這裡面
我們要看對應的 Illuminate\Database\DatabaseManager
裡面的 table()
不過,當我們進到 DatabaseManager
去找的時候,會發現根本找不到 table()
這個函數,這是怎麼一回事呢?
這邊就要講到 PHP 使用魔法函數的特性,以及 Laravel 怎麼利用這個特性了。
在 PHP 裡面,除了提供一般的物件導向程式語法以外,還提供了許多特殊的函數,可以做出開發者想要,但是物件本身沒有提供的動作。其中一種就是 __call()
,這個函數會在呼叫某個該物件不存在的函數時,先進來執行看看。
我們來看看 DatabaseManager
的 __call()
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}
return $this->connection()->$method(...$parameters);
}
所以我們發現了,一但我們試著呼叫某個 DatabaseManager
不存在的函數,他會試著去往自己的 connection
物件執行。
我們來看看 Connection
裡面是否有 table()
這個函數,結果真的有
/**
* Begin a fluent query against a database table.
*
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Contracts\Database\Query\Expression|string $table
* @param string|null $as
* @return \Illuminate\Database\Query\Builder
*/
public function table($table, $as = null)
{
return $this->query()->from($table, $as);
}
所以 DB::table()
會回傳一個 \Illuminate\Database\Query\Builder
物件,接著就是執行 get()
/**
* Execute the query as a "select" statement.
*
* @param array|string $columns
* @return \Illuminate\Support\Collection
*/
public function get($columns = ['*'])
{
$items = collect($this->onceWithColumns(Arr::wrap($columns), function () {
return $this->processor->processSelect($this, $this->runSelect());
}));
return $this->applyAfterQueryCallbacks(
isset($this->groupLimit) ? $this->withoutGroupLimitKeys($items) : $items
);
}
這就會執行一段 Query 並將取得的物件轉換為 Laravel 的 Collection 物件了。
明天我們更深入的看看這段程式是怎麼被解讀的!